#include "ChatGrpcClient.h"

ChatConPool::ChatConPool(size_t poolSize, std::string host, std::string port)
	: m_poolSize(poolSize), m_host(host), m_port(port), m_b_stop(false) 
{
	for (int i = 0; i < m_poolSize; ++i) {
		std::shared_ptr<grpc::Channel> channel = grpc::CreateChannel(host + ":" + port, grpc::InsecureChannelCredentials());

		m_connections.push(message::ChatService::NewStub(channel));
	}
}

ChatConPool::~ChatConPool()
{
	std::lock_guard<std::mutex> lock(m_mutex);
	Close();
	while (!m_connections.empty()) {
		m_connections.pop();
	}
}

void ChatConPool::Close()
{
	m_b_stop = true;
	m_cond.notify_all();
}

std::unique_ptr<message::ChatService::Stub> ChatConPool::getConnection()
{
	std::unique_lock<std::mutex> lock(m_mutex);
	m_cond.wait(lock, [this]() {
		if (m_b_stop) {
			return true;
		}

		return !m_connections.empty();
		});

	if (m_b_stop) {
		return nullptr;
	}

	auto con = std::move(m_connections.front());
	m_connections.pop();

	return con;
}

void ChatConPool::returnConnnection(std::unique_ptr<message::ChatService::Stub> con)
{
	std::lock_guard<std::mutex> lock(m_mutex);
	if (m_b_stop || !con) {
		return;
	}

	if (m_connections.size() < m_poolSize) {
		m_connections.push(std::move(con));
		m_cond.notify_one();
	}
}

ChatGrpcClient::ChatGrpcClient()
{
	auto& cfg = ConfigManager::getInstance();
	auto server_list = cfg["PeerServer"]["Servers"];

	std::vector<std::string> words;

	std::stringstream ss(server_list);
	std::string word;

	while (std::getline(ss, word, ',')) {
		words.push_back(word);
	}

	for (auto& word : words) {
		if (cfg[word]["Name"].empty()) {
			continue;
		}

		m_pools[cfg[word]["Name"]] = std::make_unique<ChatConPool>(5, cfg[word]["Host"], cfg[word]["Port"]);
	}
}
